#include <iostream>
#include <time.h>
#include <opencv2/opencv.hpp>


using namespace std;
using namespace cv;


int main(int argc, char **argv) {
    
    string configPath  = "/home/john/LJJ_SRC/opencv_test/parameter/test.yaml";

    /* 初始化 */
    FileStorage fs;
    // FileStorage fs(configPath, FileStorage::READ);

    
    /********************** 覆盖写操作 **************************/
    fs.open(configPath, FileStorage::WRITE);// 覆盖写，此步会清空 yaml 文件
    if(!fs.isOpened()){
        cerr << "fs.isOpened() return false at FileStorage::WRITE! FAIL" << endl;  
        return 1;  
    }
    // string aaa = "wewgfwgw";
    // fs << aaa << "const String &val";
    fs << "a_int_value" << 10;
    fs << "b_float_value" << 11.0;
    fs << "c_string_value" << "  Valar Morghulis  \r\n  Valar Dohaeris";
  
    fs << "d_matrix_value" << (cv::Mat_<int>(3, 3) <<   12, 22, 90, 
                                                        12, 22, 90,
                                                        12, 22, 90);

    // fs << "e_vector" << "[";
    // fs << "One" << "Two" << "Three";
    // fs << "]";
    fs << "e_vector_value" <<"[" << "One" << "Two" << "Three" << "]"; 

    // fs << "f_map" << "{";
    // fs << "One" << 1;
    // fs << "Two" << 2 ;
    // fs << "}";
    fs << "f_map_value" << "{" << "One" << 1 << "Two" << 2 << "}";
    fs.release();



    /*********************** 读取操作 **************************/
    fs.open(configPath, FileStorage::READ);
    if(!fs.isOpened()){
        cerr << "fs.isOpened() return false at FileStorage::READ! FAIL" << endl;  
        return 1;  
    }
    int a;
    float b;
    string c;
    cv::Mat d;
    vector<string> e;
    map<string, int> f;

    // 读取普通类型
    // a = (int)fs["a_int_value"];
    fs["a_int_value"]       >> a;
    fs["b_float_value"]     >> b;
    fs["c_string_value"]    >> c;
    fs["d_matrix_value"]    >> d;

    {
        FileNode n = fs["e_vector_value"];// 从序列中读取vector
        if (n.type() != FileNode::SEQ){
            cerr << "e_vector_value is not a sequence! FAIL" << endl;  
            return 1;  
        }
        n >> e;
        // // Go through the node 
        // FileNodeIterator it = n.begin(), it_end = n.end();
        // for (; it != it_end; ++it)
        //     cout << (string)*it << endl;
    }

    {
        FileNode n = fs["f_map_value"];// 从序列中读取map
        if (n.type() != FileNode::MAP){
            cerr << "f_map_value is not a MAP! FAIL" << endl;  
            return 1;  
        }
        n["Two"] >> f["Two"];// f["Two"] = (int)(n["Two"]);
        n["One"] >> f["One"];// f["One"] = (int)(n["One"]);
        // cout << "Two   maps   " << (int)(n["Two"]) << endl;
        // cout << "One   maps   " << (int)(n["One"]) << endl;
    }

    cout << "\na_int_value: "        << a << endl;
    cout << "\nb_float_value: "      << b << endl;
    cout << "\nc_string_value: \n"   << c << endl;
    cout << "\nd_matrix_value: \n"   << d << endl;
    
    cout << "\ne_vector_value (size: " << e.size() << "): " << endl;
    for (vector<string>::iterator it = e.begin(); it != e.end(); ++it){
        cout << "  " << *it << endl;
    }

    cout << "\nf_map_value (size: " << f.size() << "): " << endl;
	for(std::map<string, int>::iterator it = f.begin();it != f.end();it++){
		std::cout << "  " << it->first << ": " << it->second << endl;
        // map也存在其它的数据查找方式，这里只是遍历打印出来所有的对应值
	}
    fs.release();



    /*********************** 追加写操作 **************************/
    fs.open(configPath, FileStorage::APPEND);// 追加写，此步是在 yaml 文件末尾追加，不会清空文件
    if(!fs.isOpened()){
        cerr << "fs.isOpened() return false at FileStorage::APPEND! FAIL" << endl;  
        return 1;  
    }
    time_t rawtime; time(&rawtime); 
    fs << "time" << asctime(localtime(&rawtime));
    fs.release();



    return 0;
}

